/**
 
 * Copyright (C), 2016, 上海赛可电子商务有限公司
 
 * Date:     2016-03-21
 
 * Description: 基础类 lazyload 方法
 
 */
 
;(function(root, factory) {
	
    if (typeof define === 'function') {
        if (define.cmd) {
            define("ECar.base", function(require, exports, module) {
                "define:nomunge,require:nomunge,exports:nomunge,module:nomunge";
                return factory(root, root.ECar || (root.ECar = {}));
            });
        } else {
            define(function() {
                "define:nomunge,require:nomunge,exports:nomunge,module:nomunge";
                return factory(root, root.ECar || (root.ECar = {}));
            });
        }
    } else if (typeof exports === 'object') {
        // Node, CommonJS之类的


        module.exports = factory(root, root.ECar || (root.ECar = {}));
    } else {
        factory(root, root.ECar || (root.ECar = {}));
    }

})(this, function(root, ECar) {


    //NameSpaces 创建一个命名空间


    ECar.NameSpace = function(name, sep) {
        var s = name.split(sep || '.'),
            d = {},
            o = function(a, b, c) {
                //debugger;


                if (c < b.length) {
                    if (!a[b[c]]) {
                        a[b[c]] = {};
                    }
                    d = a[b[c]];
                    o(a[b[c]], b, c + 1);
                }
            };
        o(root, s, 0);
        return d;
    };
	
	// json转换 
	ECar.NameSpace('ECar.lazyload');
	
    /*富赟 | start*/
    // 图片懒加载 方法


    root.lazyload = ECar.lazyload || {};
    
		
	(function(){

		var w = window,
			$window = $(w),
			defaultOptions = {
				threshold                   : 0,
				failure_limit               : 0,
				event                       : 'scroll',
				effect                      : 'show',
				effect_params               : null,
				container                   : w,
				data_attribute              : 'original',
				data_srcset_attribute       : 'image-srcset',
				skip_invisible              : true,
				appear                      : emptyFn,
				load                        : emptyFn,
				vertical_only               : false,
				check_appear_throttle_time  : 300,
				url_rewriter_fn             : emptyFn,
				no_fake_img_loader          : false,
				placeholder_data_img        : '',
				// for IE6\7 that does not support data image
				placeholder_real_img        : ''
				// todo : 将某些属性用global来配置，而不是每次在$(selector).lazyload({})内配置
			},
			type // function
	
		function emptyFn(){}
	
		type = (function(){
			var object_prototype_toString = Object.prototype.toString
			return function(obj){
				// todo: compare the speeds of replace string twice or replace a regExp
				return object_prototype_toString.call(obj).replace('[object ','').replace(']','')
			}
		})()
	
		function belowthefold($element, options){
			var fold
			if(options._$container == $window){
				fold = ('innerHeight' in w ? w.innerHeight : $window.height()) + $window.scrollTop()
			}else{
				fold = options._$container.offset().top + options._$container.height()
			}
			return fold <= $element.offset().top - options.threshold
		}
	
		function rightoffold($element, options){
			var fold
			if(options._$container == $window){
				// Zepto do not support `$window.scrollLeft()` yet.
				fold = $window.width() + ($.fn.scrollLeft?$window.scrollLeft():w.pageXOffset)
			}else{
				fold = options._$container.offset().left + options._$container.width()
			}
			return fold <= $element.offset().left - options.threshold
		}
	
		function abovethetop($element, options){
			var fold
			if(options._$container == $window){
				fold = $window.scrollTop()
			}else{
				fold = options._$container.offset().top
			}
			return fold >= $element.offset().top + options.threshold  + $element.height()
		}
	
		function leftofbegin($element, options){
			var fold
			if(options._$container == $window){
				// Zepto do not support `$window.scrollLeft()` yet.
				fold = $.fn.scrollLeft?$window.scrollLeft():w.pageXOffset
			}else{
				fold = options._$container.offset().left
			}
			return fold >= $element.offset().left + options.threshold + $element.width()
		}
	
		function checkAppear($elements, options){
			var counter = 0
			$elements.each(function(i,e){
				var $element = $elements.eq(i)
				if(($element.width() <= 0 && $element.height() <= 0) || $element.css('display') === 'none'){
					return
				}
				function appear(){
					$element.trigger('_lazyload_appear')
					// if we found an image we'll load, reset the counter 
					counter = 0
				}
				// If vertical_only is set to true, only check the vertical to decide appear or not
				// In most situations, page can only scroll vertically, set vertical_only to true will improve performance
				if(options.vertical_only){
					if(abovethetop($element, options)){
						// Nothing. 
					}else if(!belowthefold($element, options)){
						appear()
					}else{
						if(++counter > options.failure_limit){
							return false
						}
					}
				}else{
					if(abovethetop($element, options) || leftofbegin($element, options)){
						// Nothing. 
					}else if(!belowthefold($element, options) && !rightoffold($element, options)){
						appear()
					}else{
						if(++counter > options.failure_limit){
							return false
						}
					}
				}
			})
		}
	
		// Remove image from array so it is not looped next time. 
		function getUnloadElements($elements){
			return $elements.filter(function(i,e){
				return !$elements.eq(i)._lazyload_loadStarted
			})
		}
	
		// throttle : https://github.com/component/throttle , MIT License
		function throttle (func, wait) {
			var ctx, args, rtn, timeoutID // caching
			var last = 0
	
			return function throttled () {
				ctx = this
				args = arguments
				var delta = new Date() - last
				if (!timeoutID)
					if (delta >= wait) call()
					else timeoutID = setTimeout(call, wait - delta)
				return rtn
			}
	
			function call () {
				timeoutID = 0
				last = +new Date()
				rtn = func.apply(ctx, args)
				ctx = null
				args = null
			}
		}
	
		var isJson = function(obj){
			var isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;    
			return isjson;
		}
		

         lazyload.init = function (obj, options) {
			 if(obj){ 
				 if(isJson(obj)){//是否是json
					options = obj;
					obj = "img";
				  }
			 }else{
				obj = "img";
			}
			$(obj).lazyload(options);

        };
		if(!$.fn.hasOwnProperty('lazyload')){
			$.fn.lazyload = function(options){
				var $elements = this,
					isScrollEvent,
					isScrollTypeEvent,
					throttleCheckAppear

				if(!$.isPlainObject(options)){
					options = {}
				}
	
				$.each(defaultOptions,function(k,v){
					if($.inArray(k,['threshold','failure_limit','check_appear_throttle_time']) != -1){ // these params can be a string
						if(type(options[k]) == 'String'){
							options[k] = parseInt(options[k],10)
						}else{
							options[k] = v
						}
					}else if(k == 'container'){ // options.container can be a seletor string \ dom \ jQuery object
						if(options.hasOwnProperty(k)){   
							if(options[k] == w || options[k] == document){
								options._$container = $window
							}else{
								options._$container = $(options[k])
							}
						}else{
							options._$container = $window
						}
						delete options.container
					}else if(defaultOptions.hasOwnProperty(k) && (!options.hasOwnProperty(k) || (type(options[k]) != type(defaultOptions[k])))){
						options[k] = v
					}
				})
	
				isScrollEvent = options.event == 'scroll'
				throttleCheckAppear = options.check_appear_throttle_time == 0?
					checkAppear
					:throttle(checkAppear,options.check_appear_throttle_time)
	
				// isScrollTypeEvent cantains custom scrollEvent . Such as 'scrollstart' & 'scrollstop'
				// https://github.com/search?utf8=%E2%9C%93&q=scrollstart
				isScrollTypeEvent = isScrollEvent || options.event == 'scrollstart' || options.event == 'scrollstop'
	
				$elements.each(function(i,e){
					var element = this,
						$element = $elements.eq(i),
						placeholderSrc = $element.attr('src'),
						originalSrcInAttr = $element.attr('data-'+options.data_attribute), // `data-original` attribute value
						originalSrc = options.url_rewriter_fn == emptyFn?
							originalSrcInAttr:
							options.url_rewriter_fn.call(element,$element,originalSrcInAttr),
						originalSrcset = $element.attr('data-'+options.data_srcset_attribute),
						isImg = $element.is('img')
	
					if($element._lazyload_loadStarted == true || placeholderSrc == originalSrc){
						$element._lazyload_loadStarted = true
						$elements = getUnloadElements($elements)
						return
					}
	
					$element._lazyload_loadStarted = false
	
					// If element is an img and no src attribute given, use placeholder. 
					if(isImg && !placeholderSrc){
						// For browsers that do not support data image.

						$element.one('error',function(){ // `on` -> `one` : IE6 triggered twice error event sometimes
					
							$element.attr('src',options.placeholder_real_img)
						}).attr('src',options.placeholder_data_img)
						
					}
					
					// When appear is triggered load original image. 
					$element.one('_lazyload_appear',function(){
						var effectParamsIsArray = $.isArray(options.effect_params),
							effectIsNotImmediacyShow
						function loadFunc(){
							// In most situations, the effect is immediacy show, at this time there is no need to hide element first
							// Hide this element may cause css reflow, call it as less as possible
							if(effectIsNotImmediacyShow){
								// todo: opacity:0 for fadeIn effect
								$element.hide()
							}
							if(isImg){
								// attr srcset first
								if(originalSrcset){
									$element.attr('srcset', originalSrcset)
								}
								if(originalSrc){
									$element.attr('src', originalSrc)
								}
							}else{
								$element.css('background-image','url("' + originalSrc + '")')
							}
							if(effectIsNotImmediacyShow){
								$element[options.effect].apply($element,effectParamsIsArray?options.effect_params:[])
							}
							$elements = getUnloadElements($elements)
						}
						if(!$element._lazyload_loadStarted){
							effectIsNotImmediacyShow = (options.effect != 'show' && $.fn[options.effect] && (!options.effect_params || (effectParamsIsArray && options.effect_params.length == 0)))
							if(options.appear != emptyFn){
								options.appear.call(element, $element, $elements.length, options)
							}
							$element._lazyload_loadStarted = true
							if(options.no_fake_img_loader || originalSrcset){
								if(options.load != emptyFn){
									$element.one('load',function(){
										options.load.call(element, $element, $elements.length, options)
									})
								}
								loadFunc()
							}else{
								$('<img />').one('load', function(){ // `on` -> `one` : IE6 triggered twice load event sometimes
									loadFunc()
									if(options.load != emptyFn){
										options.load.call(element, $element, $elements.length, options)
									}
								}).attr('src',originalSrc)
							}
						}
					})
	
					// When wanted event is triggered load original image 
					// by triggering appear.                              
					if (!isScrollTypeEvent){
						$element.on(options.event, function(){
							if (!$element._lazyload_loadStarted){
								$element.trigger('_lazyload_appear')
							}
						})
					}
				})
	
				// Fire one scroll event per scroll. Not one scroll event per image. 
				if(isScrollTypeEvent){
					options._$container.on(options.event, function(){
						throttleCheckAppear($elements, options)
					})
				}
	
				// Check if something appears when window is resized. 
				// Force initial check if images should appear when window is onload. 
				$window.on('resize load', function(){
					throttleCheckAppear($elements, options)
				})
	
				// Force initial check if images should appear. 
				$(function(){
					throttleCheckAppear($elements, options)
				})
				
				return this
			}
		}

	}());
    /*富赟 | end*/

    return ECar;

});